package com.sdu.shanyimisapi.config;

import cn.dev33.satoken.exception.NotLoginException;
import cn.hutool.json.JSONObject;
import com.sdu.shanyimisapi.exception.ShanyiMisException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.multipart.support.MissingServletRequestPartException;

/**
 * @author lihaopeng
 * @version 1.0
 * @project shanyi-mis-api
 * @description 全局异常处理类，简化返回给前端的异常信息
 * @since 2024/4/13 11:29
 */
// 该注解用于定义统一的异常处理类，而不是在每个Controller中写@ExceptionHandler。
// 加了这个注解，后端所有的异常都由这个类里的方法进行处理。
@RestControllerAdvice
@Slf4j
public class ExceptionAdvice {

    /**
     * 处理异常
     * 捕获各种异常并加以简化，返回信息为String，加上@ResponseBody注解，这个信息就会自动写到响应里面。
     * 加上@ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)，设置响应的状态码为500。
     *
     * @param e 异常
     * @return String 返回给前端的异常信息，为json格式
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    @ExceptionHandler(Exception.class) // 加了这个注解就可以捕获到各种的异常。
    public String exceptionHandler(Exception e) {
        JSONObject json = new JSONObject();
        if (e instanceof HttpMessageNotReadableException) {
            HttpMessageNotReadableException exception = (HttpMessageNotReadableException) e;
            log.error("error", exception); // 将异常的执行栈打印到后端的控制台。
            json.set("error", "请求未提交数据或者数据有误"); // 将异常信息简化后返回给前端。
        } else if (e instanceof MissingServletRequestPartException) {
            MissingServletRequestPartException exception = (MissingServletRequestPartException) e;
            log.error("error", exception);
            json.set("error", "请求提交数据错误");
        } else if (e instanceof HttpRequestMethodNotSupportedException) {
            HttpRequestMethodNotSupportedException exception = (HttpRequestMethodNotSupportedException) e;
            log.error("error", exception);
            json.set("error", "HTTP请求方法类型错误");
        }
        // 后端验证失败产生的异常
        else if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException exception = (MethodArgumentNotValidException) e;
            json.set("error", exception.getBindingResult().getFieldError().getDefaultMessage());
        }
        // 自定义异常
        else if (e instanceof ShanyiMisException) {
            log.error("执行异常", e);
            ShanyiMisException exception = (ShanyiMisException) e;
            json.set("error", exception.getMsg());
        }
        else {
            log.error("执行异常", e);
            json.set("error", "执行异常");
        }
        return json.toString();
    }

    /**
     * 处理未登录异常
     *
     * 捕获NotLoginException异常。
     * 加上@ResponseStatus(HttpStatus.UNAUTHORIZED)，设置响应的状态码为401。
     *
     * @param e 异常
     * @return String 返回给前端的异常信息，为json格式
     */
    @ResponseBody
    @ResponseStatus(HttpStatus.UNAUTHORIZED)
    @ExceptionHandler(NotLoginException.class)
    public String unLoginHandler(Exception e) {
        JSONObject json = new JSONObject();
        json.set("error", e.getMessage());
        return json.toString();
    }

}
